// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"flag"
	"fmt"
	"go/scanner"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

var (
	optDebug = flag.Bool("debug", false, "disable panic recovering")
	optO     = flag.String("o", "", "if nonblank, send the output to a named file")
	optStart = flag.String("start", "Start", "name of start production")
	optTodos = flag.String("todo", "", "insert sprintf(todo, i) calls into the output skeleton. Ex: 'TODO(\"#%d\")'")
)

func init() {
	flag.Parse()
}

func main() {
	if !*optDebug {
		defer func() {
			if e := recover(); e != nil {
				fmt.Fprintf(os.Stderr, "%s: %v\n", os.Args[0], e)
				os.Exit(1)
			}
		}()
	}

	var in []byte
	var err error
	if flag.NArg() > 1 {
		panic("atmost one input file may be specified")
	}

	switch ifname := flag.Arg(0); ifname {
	case "":
		in, err = ioutil.ReadAll(os.Stdin)
		if err != nil {
			panic(err)
		}
	default:
		in, err = ioutil.ReadFile(ifname)
		if err != nil {
			panic(err)
		}
	}

	var out io.Writer = os.Stdout
	if ofname := strings.TrimSpace(*optO); ofname != "" {
		ofile, err := os.Create(ofname)
		if err != nil {
			panic(err)
		}

		fout := bufio.NewWriter(ofile)
		defer func() {
			if err := fout.Flush(); err != nil {
				panic(err)
			}

			if err := ofile.Close(); err != nil {
				panic(err)
			}
		}()
		out = fout
	}

	if err = do(*optStart, flag.Arg(0), in, out); err == nil {
		return
	}

	errlist, ok := err.(scanner.ErrorList)
	if !ok {
		panic(err)
	}

	for _, err := range errlist {
		os.Stderr.WriteString(err.Error())
		os.Stderr.WriteString("\n")
	}
	os.Exit(1)
}
